package com.conselheiro.web.persistence.webdao;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.Query;

import com.conselheiro.web.entidade.Post;
import com.conselheiro.web.entidade.Relato;
import com.conselheiro.web.entidade.Usuario;
import com.conselheiro.web.entidade.enumeration.TipoPost;

/**
 * Dao responsável por lidar com o cadastro de relatos e conselhos
 * 
 * @author jader Abreu
 */
public class PostWebDAO extends WebDAO<Post> {

	@Override
	protected Class<Post> getClasse() {
		return Post.class;
	}

	@SuppressWarnings("unchecked")
	public List<Relato> recuperarRelatos() {
		EntityManager entityManager = getEntityManager();
		try {
			Query query = entityManager.createQuery("SELECT o FROM "
					+ getClasse().getSimpleName()
					+ " o WHERE TYPE(o) = Relato ORDER BY data DESC");

			List<Relato> relatos = query.getResultList();
			for (Relato relato : relatos) {
				try{
					relato.getUsuariosSeguindo().size();
				}catch (Exception e) {
					continue;
				}
			}
			return relatos;
		} catch (NoResultException e) {
			return null;
		} finally {
			entityManager.close();
		}
	}

	@SuppressWarnings("unchecked")
	public List<Post> buscarPosts(String stringBusca) {
		EntityManager entityManager = getEntityManager();
		String[] split = stringBusca.split(" ");
		try {
			Query query = entityManager.createQuery("SELECT o FROM "
					+ getClasse().getSimpleName() + " o WHERE "
					+ getStringParameters(split) + " ORDER BY data DESC");
			for (int i = 0; i < split.length; i++) {
				query.setParameter(split[i], "%" + split[i] + "%");
			}

			return (List<Post>) query.getResultList();
		} catch (NoResultException e) {
			return null;
		} finally {
			entityManager.close();
		}
	}

	private String getStringParameters(String[] splitStrings) {
		StringBuilder stringBuilder = new StringBuilder();
		for (int i = 0; i < splitStrings.length; i++) {
			stringBuilder.append(" descricao LIKE ");
			stringBuilder.append(":");
			stringBuilder.append(splitStrings[i]);
			if (i < (splitStrings.length - 1)) {
				stringBuilder.append(" or ");
			}
			stringBuilder.append(" ");
		}

		return stringBuilder.toString();
	}

	public Relato recuperarRelato(long idRelato) {
		EntityManager entityManager = getEntityManager();
		try {
			Query query = entityManager.createQuery("SELECT o FROM "
					+ getClasse().getSimpleName()
					+ " o WHERE TYPE(o) = Relato ORDER BY data DESC");

			Relato relato = (Relato)query.getSingleResult();
			relato.getUsuariosSeguindo().size();
			return relato;
		} catch (NoResultException e) {
			return null;
		} finally {
			entityManager.close();
		}
	}

	@SuppressWarnings("unchecked")
	public List<Relato> getRelatosPorUsuario(Usuario usuario, int firstResult,
			int maxResults) {
		EntityManager entityManager = getEntityManager();
		try {
			Query query = entityManager
					.createQuery("SELECT o FROM "
							+ getClasse().getSimpleName()
							+ " o WHERE TYPE(o) = Relato AND o.usuario = :usuario ORDER BY data DESC");
			query.setParameter("usuario", usuario);
			if (firstResult >= 0 && maxResults >= 0) {
				query.setFirstResult(firstResult);
				query.setMaxResults(maxResults);
			}
			List<Relato> relatos = query.getResultList();
			for (Relato relato : relatos) {
				relato.getUsuariosSeguindo().size();
			}
			return relatos;
		} finally {
			entityManager.close();
		}
	}

	@SuppressWarnings("unchecked")
	public List<Relato> getRelatosAconselhadosPorUsuario(Usuario usuario,
			int firstResult, int maxResults) {
		EntityManager entityManager = getEntityManager();
		try {
			Query query = entityManager
					.createQuery("SELECT c.relato FROM "
							+ getClasse().getSimpleName()
							+ " c WHERE TYPE(c) = Conselho AND c.usuario = :usuario ORDER BY c.data DESC");
			query.setParameter("usuario", usuario);
			if (firstResult >= 0 && maxResults >= 0) {
				query.setFirstResult(firstResult);
				query.setMaxResults(maxResults);
			}
			List<Relato> relatos = query.getResultList();
			for (Relato relato : relatos) {
				relato.getUsuariosSeguindo().size();
			}
			return relatos;
		} finally {
			entityManager.close();
		}
	}

	@SuppressWarnings("unchecked")
	public List<Relato> getLinhaDoTempoPorUsuario(Usuario usuario,
			int firstResult, int maxResults) {
		EntityManager entityManager = getEntityManager();
		try {
			Query query = entityManager
					.createQuery("SELECT c.relato FROM "
							+ getClasse().getSimpleName()
							+ " c WHERE TYPE(c) = Conselho AND c.usuario = :usuario UNION SELECT o FROM "
							+ getClasse().getSimpleName()
							+ " o WHERE TYPE(o) = Relato AND o.usuario = :usuario");
			query.setParameter("usuario", usuario);
			if (firstResult >= 0 && maxResults >= 0) {
				query.setFirstResult(firstResult);
				query.setMaxResults(maxResults);
			}
			return query.getResultList();
		} finally {
			entityManager.close();
		}
	}

	public long getTotalRelatosUsuario(String login) {
		EntityManager entityManager = getEntityManager();
		try {
			Query query = entityManager.createQuery("SELECT COUNT(o) FROM "
					+ getClasse().getSimpleName()
					+ " o WHERE TYPE(o) = Relato AND o.usuario.login = :login");
			query.setParameter("login", login);
			return (Long) query.getSingleResult();
		} finally {
			entityManager.close();
		}
	}

	public long getTotalConselhosUsuario(String login) {
		EntityManager entityManager = getEntityManager();
		try {
			Query query = entityManager
					.createQuery("SELECT COUNT(o) FROM "
							+ getClasse().getSimpleName()
							+ " o WHERE TYPE(o) = Conselho AND o.usuario.login = :login");
			query.setParameter("login", login);
			return (Long) query.getSingleResult();
		} finally {
			entityManager.close();
		}
	}

	public TipoPost getAreaInteresseUsuario(String login) {
		EntityManager entityManager = getEntityManager();
		try {
			Query query = entityManager.createQuery("SELECT o.tipo FROM "
					+ getClasse().getSimpleName()
					+ " o WHERE o.usuario.login = :login"
					+ " GROUP BY o.tipo ORDER BY COUNT(o) DESC");
			query.setParameter("login", login).setMaxResults(1);
			return (TipoPost) query.getSingleResult();
		} catch (Exception e) {
			return null;
		} finally {
			entityManager.close();
		}
	}

}
